﻿/*layCalendar
 * @Author: 王洪刚
 * @Version:V1.1
 * @Date: 2021-4-20
 * @Last Modified: 2021-4-28 14:45:00
 * @Desc:
 * 基于layui的日历控件，按月份显示，默认显示当前的月份。支持日期的类型显示 默认类型有节假日和补班
 * 注意：日历控件的右键菜单依赖于jquery.contextMenu.js组件
 * 
 * 组件属性说明
 * elem:必需项 使用jq选择器
 * 
 * holidayType:假日的类型 
 *  默认值为
 *  [{
 *      id:0,
 *      menuitem:
 *          [{
 *              key:'add',
 *              name:'添加假日',
 *              icon:'add'
 *          }]
 *  },
 *  {
 *      id:1,
 *      name:'节假日',
 *      caption:'假',
 *      daycolor:'#000000',
 *      color:'#f52e2e',
 *      menuitem:
 *          [{
 *              key:'modify',
 *              name:'修改假日',
 *              icon:'edit'
 *          },
 *          {
 *              key:'delete',
 *              name:'删除假日',
 *              icon:'delete'
 *          }]
 *   },
 *  {
 *      id:2,
 *      name:'补班',
 *      caption:'班',
 *      daycolor:'#FF0000',
 *      color:'#cbcbcb',
 *      menuitem:
 *          [{
 *              key:'modify',
 *              name:'修改假日',
 *              icon:'edit'
 *          },
 *          {
 *              key:'delete',
 *              name:'删除假日',
 *              icon:'delete'
 *          }]
 *  }]
 *  id表示假日类型 name表示假日类型的名称 caption表示在日历中显示的标识文字 daycolor表示日期文字的颜色 color表示caption标识文字的颜色 
 *  menuitem表示该日期类型显示的右键菜单 key 菜单的键值 name 菜单显示的名称 icon 菜单显示的图标
 * 
 *  
 * holidayurl:查询月份假日信息的请求地址 GET模式 参数为month=yyyy-MM，返回的数据格式为{Success:true,Data:[],Msg:null},Success表示请求数据是否成功,Data为假日信息的列表.
 * 
 * value:默认当前显示的月份 格式为yyyy-MM
 * 
 * menucallback: function (itemkey, obj){} 菜单的回调方法 itemKey 表示菜单的key值,obj表示返回的日期对象
 * obj数据的结构
 * Date 触发菜单的日期 格式为yyyy-MM-dd
 * DateType 日期类型 对应holidayType的id值
 * HolidayID 假期的后台ID号
 * BeginDate 假期的开始时间 格式 yyyy-MM-dd HH:mm:ss
 * EndDate 假期的结束时间 格式 yyyy-MM-dd HH:mm:ss
 * 
 * 假日信息数据格式
 * {
 *      ID:'1',//假日对应的ID值
 *      DateType:1,//假期类型 对应holidayType的id值
 *      BeginDate:'2021-01-01 00:00:00',//开始日期
 *      EndDate:'2021-01-03 23:59:59'//结束日期 范围时间使用
 * }
 * 
 * =============================================================
 * 调用示例
 * html
 * 引用css
 * <link href="~/lib/jquerycontextmenu/jquery.contextMenu.css" rel="stylesheet" />
 *  <link href="~/lib/layui/ext/layCalendar.css" rel="stylesheet" />
 *  引用js
 *  <script type="text/javascript" src="~/lib/jquerycontextmenu/jquery.contextMenu.js"></script>
 *  
 * <div id="calendar1" lay-filter="calendar"></div>
 * 
 * 
 * js
 * layui.use(['jquery', 'layCalendar'], function () {
 * var $ = layui.$;
 * var layCalendar = layui.layCalendar;
 * 初始化控件
 * layCalendar.render({
 *      elem: '#calendar1',
 *      holidayurl: '/HolidayInfo/GetHolidayByMonth',
 *      menucallback: function (itemKey, data) {
 *
 *      }
 *  });
 *  刷新控件
 *  layCalendar.reload('calendar');
 *  });
 * */
layui.define(["laydate", "laytpl"], function (exports) {
    "use strict";
    var moduleName = 'layCalendar', _layui = layui, laytpl = _layui.laytpl
        , $ = _layui.$, laydate = _layui.laydate;
    var configs = {
        elem: '',//组件
        holidayType: [{ id: 0, menuitem: [{ key: 'add', name: '添加假日', icon: 'add' }] }, { id: 1, name: '节假日', caption: '假', daycolor: '#000000', color: '#f52e2e', menuitem: [{ key: 'modify', name: '修改假日', icon: 'edit' }, { key: 'delete', name: '删除假日', icon: 'delete' }] }, { id: 2, name: '补班', caption: '班', daycolor: '#FF0000', color: '#cbcbcb', menuitem: [{ key: 'modify', name: '修改假日', icon: 'edit' }, { key: 'delete', name: '删除假日', icon: 'delete' }] }],
        value: new Date(),
        menucallback: function (itemkey, obj) {
            return true;
        }
    };
    var thiscfg = {};
    var parseDate = function (data) {
        var strs = data.split(' ');
        if (strs.length == 2) {
            var sd = strs[0].split('-');
            var st = strs[1].split(':');
            var date = new Date(sd[0], parseInt(sd[1]) - 1, sd[2], st[0], st[1], st[2], 0);
            return date;
        }
        else {
            var date = new Date(strs[0].replace(/-/, "/"));
            return date;
        }
    };
    var dateFormat = function (dt,fmt) {
        var o = {
            "M+": dt.getMonth() + 1,                 //月份
            "d+": dt.getDate(),                    //日
            "h+": dt.getHours(),                   //小时
            "m+": dt.getMinutes(),                 //分
            "s+": dt.getSeconds(),                 //秒
            "q+": Math.floor((dt.getMonth() + 3) / 3), //季度
            "S": dt.getMilliseconds()             //毫秒
        };
        if (/(y+)/.test(fmt))
            fmt = fmt.replace(RegExp.$1, (dt.getFullYear() + "").substr(4 - RegExp.$1.length));
        for (var k in o)
            if (new RegExp("(" + k + ")").test(fmt))
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        return fmt;
    };
    var newID = function (idstr, num) {
        var dom = $('#' + idstr + '-' + num);
        if (dom.length != 0) {
            num++;
            return newID(idstr, num);
        }
        return idstr + '-' + num;
    };
    var loadcur = function ($this) {
        var month = $this.find('input[class="layui-input"]').val();
        load($this, month);

    };
    var load = function ($this, value) {
        var id_this = $this.attr('id');
        if (id_this == null) {
            id_this = newID('laycalendar', 1);
            $this.attr('id', id_this);
        }
        var year = value.split('-')[0];
        var month = parseInt(value.split('-')[1]);
        var curday = new Date();
        curday.setFullYear(year, month - 1, 1);
        var rows = $this.find('div[class="layui-row layui-calendar-body"]');
        var rowIndex = 0;
        var week = curday.getDay();
        if (week == 0) {
            week = 7;
        }
        var rf = rows[rowIndex].children;
        for (var i = 0; i < week - 1; i++) {
            $(rf[i]).empty();
            $(rf[i]).removeAttr('name');
            $(rf[i]).removeAttr('lay-date');
            $(rf[i]).removeAttr('lay-dateType');
            $(rf[i]).unbind('contextmenu');
            $(rf[i]).bind("contextmenu", function (e) { return false; });
        }
        while (curday.getMonth() == month - 1) {
            var dtstr = dateFormat(curday, 'yyyy-MM-dd');
            var DateType = 0;
            $(rf[week - 1]).empty();
            $(rf[week - 1]).attr('lay-date', dtstr);
            $(rf[week - 1]).attr('lay-dateType', DateType);
            $(rf[week - 1]).append('<label style="color:#000000;" name="day">' + curday.getDate() + '</label>');
            $(rf[week - 1]).unbind('contextmenu');
            curday = curday.setDate(curday.getDate() + 1);
            curday = new Date(curday);
            week = curday.getDay();
            if (week == 0) {
                week = 7;
            }
            if (week == 1) {
                rowIndex += 1;
                if (rowIndex >= rows.length) {
                    rf = null;
                }
                else {
                    rf = rows[rowIndex].children;
                }
            }
        }
        if (rf != null) {
            for (var j = rowIndex; j < 6; j++) {
                for (var i = week - 1; i < 7; i++) {
                    $(rf[i]).empty();
                    $(rf[i]).removeAttr('name');
                    $(rf[i]).removeAttr('lay-date');
                    $(rf[i]).removeAttr('lay-dateType');
                    $(rf[i]).unbind('contextmenu');
                    $(rf[i]).bind("contextmenu", function (e) { return false; });
                }
                week = 0;
                rowIndex++;
                if (rowIndex >= rows.length) {
                    rf = null;
                }
                else {
                    rf = rows[rowIndex].children;
                }
            }
        }
        loadh($this, value);
    };
    var loadh = function ($this,value) {
        var id_this = $this.attr('id');
        if (id_this == null) {
            id_this = newID('laycalendar', 1);
            $this.attr('id', id_this);
        }
        var cindex = layer.load();
        $.get({
            url: thiscfg.holidayurl,
            data: { month: value },
            success: function (result) {
                layer.close(cindex);
                if (result.Success) {
                    if (result.Data != null && result.Data.length > 0) {
                        $.each(result.Data, function (index, val) {
                            var typecfg = thiscfg.holidayType.find(function (v, i) { return v.id == val.DateType });
                            var bdate = parseDate(val.BeginDate);
                            var edate = parseDate(val.EndDate);
                            var strdt = dateFormat(bdate, 'yyyy-MM-dd');
                            while (bdate <= edate) {
                                var div = $this.find('div[lay-date="' + strdt + '"]');
                                if (div.length > 0) {
                                    var hl = $(div).find('label[name="holiday"]');
                                    var dl = $(div).find('label[name="day"]');
                                    if (hl.length == 0) {
                                        $(div).append('<label name="holiday" style="color:' + typecfg.color + '">' + typecfg.caption + '</label>')
                                    }
                                    else {
                                        $(hl).empty();
                                        $(hl).append(typecfg.caption);
                                        $(hl).css('color', typecfg.color);
                                    }
                                    $(dl).css('color', typecfg.daycolor);
                                    $(div).attr('lay-dateType', val.DateType);
                                    $(div).attr('lay-data', JSON.stringify(val));
                                }
                                bdate = bdate.setDate(bdate.getDate() + 1);
                                bdate = new Date(bdate);
                                strdt = dateFormat(bdate, 'yyyy-MM-dd');
                            }
                        });
                    }
                    $.each(thiscfg.holidayType, function (index, val) {
                        var selid = '#' + id_this + ' .layui-calendar-body div[lay-datetype="' + val.id + '"]';
                        if (val.menuitem != null && val.menuitem.length > 0) {
                            var menuitem = {};
                            for (var i = 0; i < val.menuitem.length; i++) {
                                menuitem[val.menuitem[i].key] = { name: val.menuitem[i].name, icon: val.menuitem[i].icon };
                            }
                            $.contextMenu({
                                selector: selid,
                                items: menuitem,
                                callback: function (itemKey, obj) {
                                    var div = obj.$trigger;
                                    var strdt = $(div).attr('lay-date');
                                    var dttype = $(div).attr('lay-dateType');
                                    var data = $(div).attr('lay-data');
                                    var dataobj = data == null || data == '' || data == 'undefined' ? {} : JSON.parse(data);
                                    var postdata = {};
                                    postdata.Date = strdt;
                                    postdata.DateType = dttype;
                                    if (dataobj.ID != null) {
                                        postdata.HolidayID = dataobj.ID;
                                        postdata.BeginDate = dataobj.BeginDate;
                                        postdata.EndDate = dataobj.EndDate;
                                    }
                                    thiscfg.menucallback(itemKey, postdata);
                                }
                            });
                        }
                        else {
                            $(selid).bind("contextmenu", function (e) { return false; });
                        }
                    });
                }
                else {
                    layer.msg(result.Msg);
                }
            }
        }); 
        var year = value.split('-')[0];
        var month = parseInt(value.split('-')[1]);
    }
    var loadHoliday = function ($this, thiscfg) {
        $this.attr('lay-data', JSON.stringify(thiscfg));
        $this.addClass('layui-calendar');
        $this.empty();
        var id_this = $this.attr('id');
        if (id_this == null) {
            id_this = newID('laycalendar', 1);
            $this.attr('id', id_this);
        }
        var id_laydate = newID('laycalendar-laydate', 1);
        var context = '<div class="layui-row">'
            + '<form class="layui-form">'
            + '<div class="layui-form-item">'
            + '<div class="layui-inline">'
            + '<label class="layui-form-label">月份</label>'
            + '<div class="layui-inline layui-calendar-page" data-event="prev">'
            + '<i class="layui-icon layui-icon-prev"></i>'
            + '</div>'
            + '<div class="layui-inline">'
            + '<input type="text" class="layui-input" id="'
            + id_laydate
            + '" autocomplete="off" />'
            + '</div>'
            + '<div class="layui-inline layui-calendar-page" data-event="next">'
            + '<i class="layui-icon layui-icon-next"></i>'
            + '</div>'
            + '</div>'
            + '</div>'
            + '</form >'
            + '</div >';
        $this.append(context);
        context = '<div class="layui-row layui-calendar-title">'
            + '<div><label>一</label></div >'
            + '<div><label>二</label></div>'
            + '<div><label>三</label></div>'
            + '<div><label>四</label></div>'
            + '<div><label>五</label></div>'
            + '<div><label>六</label></div>'
            + '<div><label>日</label></div>'
            + '</div>';
        $this.append(context);
        for (var i = 0; i < 6; i++) {
            context = '<div class="layui-row layui-calendar-body">'
                + '<div></div>'
                + '<div></div>'
                + '<div></div>'
                + '<div></div>'
                + '<div></div>'
                + '<div></div>'
                + '<div></div>'
                + '</div >';
            $this.append(context);
        }
        laydate.render({
            elem: '#' + id_laydate,
            type: 'month',
            value: thiscfg.value,
            done: function (value, date, endDate) {
                load($this, value);
            }
        });
        var curval = $('#' + id_laydate).val();
        load($this, curval);
        $('.layui-calendar-page').on('click', function () {
            var evt = $(this).data('event');
            privateactive[evt] ? privateactive[evt].call(this) : '';
        });
    };
    var privateactive = {
        prev: function () {
            var $this = $(thiscfg.elem);
            var dtelem = $this.find('input[class="layui-input"]');
            var value = dtelem.val();
            var year = parseInt(value.split('-')[0]);
            var month = parseInt(value.split('-')[1]);
            if (month == 1) {
                year -= 1;
                month = 12;
            }
            else {
                month -= 1;
            }
            var newvalue = (Array(4).join(0) + year.toString()).slice(-4);
            newvalue += '-' + (Array(2).join(0) + month.toString()).slice(-2);
            dtelem.val(newvalue);
            load($this, newvalue);
        },
        next: function () {
            var $this = $(thiscfg.elem);
            var dtelem = $this.find('input[class="layui-input"]');
            var value = dtelem.val();
            var year = parseInt(value.split('-')[0]);
            var month = parseInt(value.split('-')[1]);
            if (month == 12) {
                year += 1;
                month = 1;
            }
            else {
                month += 1;
            }
            var newvalue = (Array(4).join(0) + year.toString()).slice(-4);
            newvalue += '-' + (Array(2).join(0) + month.toString()).slice(-2);
            dtelem.val(newvalue);
            load($this, newvalue);
        }
    };
    var active = {

        render: function (config) {
            //初始化配置项
            
            if (config != null) {
                thiscfg.elem = config.elem != null ? config.elem : configs.elem;
                thiscfg.holidayType = config.holidayType != null ? config.holidayType : configs.holidayType;
                thiscfg.holidayurl = config.holidayurl != null ? config.holidayurl : configs.holidayurl;
                thiscfg.menucallback = config.menucallback != null ? config.menucallback : configs.menucallback;
                thiscfg.value = config.value != null ? config.value : configs.value;
            }
            else {
                thiscfg = configs;
            }
            var $this = $(thiscfg.elem);
            loadHoliday($this, thiscfg);
        },
        reload: function (filter) {
            var selstr = filter == null ? '.layui-calendar' : 'div[lay-filter="' + filter + '"],.layui-calendar';
            var divs = $(selstr);
            for (var i = 0; i < divs.length; i++) {
                loadcur($(divs[i]));
            }
            
        }
    };

    exports(moduleName, active);
});